﻿using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Globalization;
using AudiPyme.BLL;
using System.IO;
using System.Data;
using AudiPyme.DAL;
using System.Web.UI.DataVisualization;
using System.Web.UI.DataVisualization.Charting;
using System.Drawing;
using System.Web.UI.HtmlControls;



namespace AudiPyme.UI
{
    //Clase interna para formatear los valores de los controles que aparecen en la interfaz
    internal class ControlEmpresaAux
    {
        int idControl;
        String nombre;
        String objetivoControl;
        String valor;
        String descripcion;

        public ControlEmpresaAux()
        {
        }

        public ControlEmpresaAux(int IdControl, String Nombre, String ObjetivoControl, String ValorRespuesta, String Descripcion)
        {
            idControl = IdControl;
            nombre = Nombre;
            objetivoControl = ObjetivoControl;
            valor = ValorRespuesta;
            descripcion = Descripcion;
        }

        public int IdControl
        {
            get { return idControl; }
            set { idControl = value; }
        }
        public String Nombre
        {
            get { return nombre; }
            set { nombre = value; }
        }
        public String ObjetivoControl
        {
            get { return objetivoControl; }
            set { objetivoControl = value; }
        }
        public String Valor
        {
            get { return valor; }
            set { valor = value; }
        }
        public String Descripcion
        {
            get { return descripcion; }
            set { descripcion = value; }
        }
    }

    public partial class ControlesPrincipal : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!this.IsPostBack)
            {
                String NombreUsuario = (String)Session["nombreUsuario"];
                int EmpresaUsuario = UsuariosFactory.EmpresaUsuario(NombreUsuario);
                if (EmpresaUsuario != 0)
                {
                    bool tieneControles = ControlesEmpresaFactory.TieneControlesEmpresa(EmpresaUsuario);
                    if (tieneControles)
                    {
                        PanelOpcClasif.Visible = true;
                        PanelChart.Visible = true;
                        //Inicialmente se muestra el Chart con los controles agrupados por respuestas
                        PintaChart("RespuestasControles", null);
                    }
                    else
                    {
                        MuestraMensaje("La Empresa no ha respondido a los controles para calcular el Nivel de Madurez Actual");
                    }
                }
                else
                {
                    MuestraMensaje("No hay una empresa asociada al usuario " + NombreUsuario);
                }
            }
        }

        //Método que muestra la información elegida en un chart
        private void PintaChart(String opcion, List<int> Rangos)
        {
            try
            {
                //Recogemos la empresa asociada al usuario que inició la sesión
                String NombreUsuario = (String)Session["nombreUsuario"];
                int EmpresaUsuario = UsuariosFactory.EmpresaUsuario(NombreUsuario);
                //Seteamos el chart a visible por si venimos de una condición de error
                Chart1.Visible = true;
                switch (opcion)
                {
                    //Dependiendo de la opcion elegida en el DropDownList, el Chart mostrará los controles 
                    //agrupados según el criterio seleccionado
                    case "RespuestasControles":
                        PnlDominios.Visible = false;
                        LblOpcion.Text = "Respuestas de los Controles";
                        List<String> TiposRespuestas = ControlesFactory.TiposRespuestasControles();
                        List<int> NumRespControles = ControlesEmpresaFactory.NumeroControlesTipoRespuesta(EmpresaUsuario);
                        if (HayControles(NumRespControles))
                        {
                            PanelChart.Visible = true;
                            for (int i = 0; i < TiposRespuestas.Count(); i++)
                            {
                                Chart1.Series["Series1"].Points.AddXY(TiposRespuestas[i], NumRespControles[i]);
                            }
                            this.Chart1.Series["Series1"].ToolTip = "Número de Controles con Respuesta #AXISLABEL : #VALY. Pinche aquí para verlos";
                        }
                        else
                        {
                            MuestraMensaje("No hay activos definidos para la empresa");
                            PanelChart.Visible = false;
                        }
                        break;
                    case "ObjetivosControl":
                        LblOpcion.Text = "Objetivos de Control";
                        List<int> LNumRespControles = ControlesEmpresaFactory.NumeroControlesTipoRespuesta(EmpresaUsuario);
                        if (HayControles(LNumRespControles))
                        {
                            PanelChart.Visible = true;
                            IQueryable<Dominios> DominiosNorma = DominiosFactory.RecogeDominios();
                            var Domi = from D in DominiosNorma
                                       orderby D.IdDominios
                                       select new { D.Nombre, D.IdDominios };
                            DdlDominio.DataSource = Domi;
                            DdlDominio.DataTextField = "Nombre";
                            DdlDominio.DataValueField = "IdDominios";
                            DdlDominio.DataBind();
                            PnlDominios.Visible = true;
                            int IdDominioSelect = int.Parse(DdlDominio.SelectedValue);
                            PintaChartDominio(IdDominioSelect);
                        }
                        else
                        {
                            MuestraMensaje("No hay activos definidos para la empresa");
                            PanelChart.Visible = false;
                        }
                        break;
                }
                //Transparencia a las barras del chart
                Chart1.ApplyPaletteColors();
                foreach (var serie in Chart1.Series)
                    serie.Color = Color.FromArgb(220, serie.Color);
                UpdatePanel3.Update();
            }
            catch (Exception e1)
            {
                e1.ToString();
                MuestraMensaje("Error al actualizar el gráfico");
            }
        }

        private bool HayControles(List<int> ListaControles)
        {
            bool hay = false;
            for (int i = 0; i < ListaControles.Count(); i++)
            {
                if (ListaControles[i] != 0)
                {
                    hay = true;
                    return hay;
                }
            }
            return hay;
        }

        private void PintaChartDominio(int IdDominioSelect)
        {
            try
            {
                //Pinta el gráfico según el objetivo de control seleccionado
                List<String> ObjetivosControl = ObjetivosControlFactory.ObjetivosControl(IdDominioSelect);
                List<int> NumContrObjetivControl = ObjetivosControlFactory.NumeroControlesObjetivoControl(IdDominioSelect);
                for (int i = 0; i < ObjetivosControl.Count(); i++)
                {
                    Chart1.Series["Series1"].Points.AddXY(ObjetivosControl[i], NumContrObjetivControl[i]);
                }
                this.Chart1.Series["Series1"].ToolTip = "Número de Controles cuyo Objetivo de Control es #AXISLABEL : #VALY. Pinche aquí para verlos";
                //Transparencia a las barras del chart
                Chart1.ApplyPaletteColors();
                foreach (var serie in Chart1.Series)
                    serie.Color = Color.FromArgb(220, serie.Color);
                UpdatePanel3.Update();
            }
            catch (Exception e1)
            {
                e1.ToString();
                MuestraMensaje("Error al actualizar el gráfico");
            }
        }

        protected void MuestraMensaje(string Mensaje)
        {
            StringBuilder SB = new StringBuilder();
            SB.Append("alert('");
            SB.Append(Mensaje.Replace("\n", "\\n").Replace("\r", "").Replace("'", "\\'"));
            SB.Append("');");
            ScriptManager.RegisterStartupScript(this.Page, this.GetType(), "showalert", SB.ToString(), true);
        }

        private void LlenaGridView(String opcion, String Parametro)
        {
            try
            {
                String NombreUsuario = (String)Session["nombreUsuario"];
                int EmpresaUsuario = UsuariosFactory.EmpresaUsuario(NombreUsuario);
                List<ControlEmpresaAux> ListaControles = new List<ControlEmpresaAux>();
                //Dependiendo de la opcion elegida en el DropDownList y de la barra elegida en el Chart el GridView mostrará los controles 
                //agrupados según la opción seleccionada y filtrados según la barra del Chart elegida
                switch (opcion)
                {
                    case "RespuestasControles":
                        //Recojo el valor del tipo de respuesta seleccionado en el chart
                        String TipoActivo = LblTipoActivo.Text;
                        //Si ya se ha añadido los dos puntos, no se vuelven a añadir
                        if (!LblOpcion.Text.Contains(":"))
                        {
                            LblOpcion.Text = LblOpcion.Text + ":";
                        }
                        ModeloContainer agenteBD = new ModeloContainer();
                        IQueryable<ControlesEmpresa> ContrEmprResp = ControlesEmpresaFactory.RecogeControlesEmpresaResp(EmpresaUsuario, SerializaParametro(Parametro));
                        foreach (ControlesEmpresa ContrEmR in ContrEmprResp)
                        {
                            ControlEmpresaAux nuevoControl = new ControlEmpresaAux();
                            nuevoControl.IdControl = ContrEmR.IdControl;
                            nuevoControl.Valor = ControlesEmpresaNegocio.DesSerializaRespuesta(ContrEmR.Valor);
                            nuevoControl.Nombre = ControlesFactory.NombreControl(nuevoControl.IdControl);
                            nuevoControl.ObjetivoControl = ObjetivosControlFactory.ObjetivoControl(nuevoControl.IdControl);
                            nuevoControl.Descripcion = ControlesFactory.DescripcionControl(nuevoControl.IdControl);
                            ListaControles.Add(nuevoControl);
                        }
                        GVControles.DataSource = ListaControles;
                        DataBind();
                        break;
                    case "ObjetivosControl":
                        //Recojo el valor del tipo de objetivo de control escogido en el chart
                        String ObjContrSelec = LblTipoActivo.Text;
                        //Si ya se ha añadido los dos puntos, no se vuelven a añadir
                        if (!LblOpcion.Text.Contains(":"))
                        {
                            LblOpcion.Text = LblOpcion.Text + ":";
                        }
                        IQueryable<ControlesEmpresa> ContrEmprObj = ControlesEmpresaFactory.RecogeControlesEmpresaObjCtr(EmpresaUsuario, Parametro);
                        foreach (ControlesEmpresa ContrEmR in ContrEmprObj)
                        {
                            ControlEmpresaAux nuevoControl = new ControlEmpresaAux();
                            nuevoControl.IdControl = ContrEmR.IdControl;
                            nuevoControl.Valor = ControlesEmpresaNegocio.DesSerializaRespuesta(ContrEmR.Valor);
                            nuevoControl.Nombre = ControlesFactory.NombreControl(nuevoControl.IdControl);
                            nuevoControl.ObjetivoControl = ObjetivosControlFactory.ObjetivoControl(nuevoControl.IdControl);
                            nuevoControl.Descripcion = ControlesFactory.DescripcionControl(nuevoControl.IdControl);
                            ListaControles.Add(nuevoControl);
                        }
                        GVControles.DataSource = ListaControles;
                        DataBind();
                        break;
                }
                UpdatePanel4.Update();
            }
            catch (Exception e1)
            {
                e1.ToString();
                MuestraMensaje("Error al actualizar los valores de la tabla");
            }
        }

        //Permite serializar los valores de las respuestas de los controles
        private String SerializaParametro(String Parametro)
        {
            switch (Parametro)
            {
                case "PARCIALMENTE":
                    return "PARC";
                case "NO APLICA":
                    return "N/A";
                default:
                    return Parametro;
            }

        }

        protected void DdlControles_SelectedIndexChanged(object sender, EventArgs e)
        {
            //Recogemos la empresa asociada al usuario que inició la sesión
            String NombreUsuario = (String)Session["nombreUsuario"];
            int EmpresaUsuario = UsuariosFactory.EmpresaUsuario(NombreUsuario);
            String opcion = DdlControles.SelectedValue;
            LblOpcion.Text = opcion;
            //Ponemos el label a vacío por si veníamos de otra opción
            LblTipoActivo.Text = "";
            //Bindeamos el GridView a null para que si saltamos de clasificación no se nos muestre el GV anterior
            GVControles.DataSource = null;
            UpdatePanel4.Update();
            DataBind();
            PintaChart(opcion, null);
        }

        protected void Chart1_Click(object sender, ImageMapEventArgs e)
        {
            try
            {
                //Recogemos la opción elegida en el DropDownList
                String opcion = DdlControles.SelectedValue;
                //Si hubiera una fila seleccionada para editar la deseleccionamos
                GVControles.EditIndex = -1;
                //Recogemos el valor seleccionado en el chart
                String Parametro = e.PostBackValue;
                switch (opcion)
                {
                    case "RespuestasControles":
                        DesSerializaRespuesta(Parametro);
                        PintaChart(opcion, null);
                        LlenaGridView(opcion, Parametro);
                        break;
                    case "ObjetivosControl":
                        LblTipoActivo.Text = Parametro;
                        int IdDominioSelect = int.Parse(DdlDominio.SelectedValue);
                        PintaChartDominio(IdDominioSelect);
                        LlenaGridView(opcion, Parametro);
                        break;
                    default:
                        PintaChart("RespuestasControles", null);
                        break;
                }
            }
            catch (Exception e1)
            {
                e1.ToString();
                MuestraMensaje("Error al actualizar los valores de la tabla tras la selección");
            }

        }

        //Permite deserializar los valores de las respuestas
        private void DesSerializaRespuesta(String parametro)
        {
            switch (parametro)
            {
                case "PARC":
                    LblTipoActivo.Text = "PARCIALMENTE";
                    break;
                case "N/A":
                    LblTipoActivo.Text = "NO APLICA";
                    break;
                default:
                    LblTipoActivo.Text = parametro;
                    break;
            }
        }


        protected void GVControles_RowEditing(object sender, GridViewEditEventArgs e)
        {
            try
            {
                //Seleccionamos la fila seleccionada
                GVControles.EditIndex = e.NewEditIndex;
                //Recogemos el tipo de opcion elegida en DdlControles
                String opcion = DdlControles.SelectedValue;
                String Parametro = LblTipoActivo.Text;
                switch (opcion)
                {
                    case "RespuestasControles":
                        String ParametroSer = SerializaRespuesta(Parametro);
                        //PintaChart(opcion, null);
                        LlenaGridView(opcion, ParametroSer);
                        break;
                    case "ObjetivosControl":
                        int IdDominioSelect = int.Parse(DdlDominio.SelectedValue);
                        //PintaChartDominio(IdDominioSelect);
                        LlenaGridView(opcion, Parametro);
                        break;
                    default:
                        PintaChart("RespuestasControles", null);
                        break;
                }
            }
            catch (Exception e1)
            {
                e1.ToString();
                MuestraMensaje("No se pudo editar el control");
            }
        }

        protected void GVControles_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
        {
            try
            {
                //Deseleccionamos la fila
                GVControles.EditIndex = -1;
                //Recogemos el tipo de ordenación de los activos seleccionado en DdlActivos
                String opcion = DdlControles.SelectedValue;
                String Parametro = LblTipoActivo.Text;
                switch (opcion)
                {
                    case "RespuestasControles":
                        String ParametroSer = SerializaRespuesta(Parametro);
                        //PintaChart(opcion, null);
                        LlenaGridView(opcion, ParametroSer);
                        break;
                    case "ObjetivosControl":
                        int IdDominioSelect = int.Parse(DdlDominio.SelectedValue);
                        //PintaChartDominio(IdDominioSelect);
                        LlenaGridView(opcion, Parametro);
                        break;
                    default:
                        //PintaChart("RespuestasControles", null);
                        break;
                }
            }
            catch (Exception e1)
            {
                e1.ToString();
                MuestraMensaje("Error al editar el control");
            }
        }

        protected void GVControles_RowUpdating(object sender, GridViewUpdateEventArgs e)
        {
            try
            {
                Page.Validate("ValDdlValor");
                if (Page.IsValid)
                {
                    //Recogemos la empresa asociada al usuario que inició la sesión
                    String NombreUsuario = (String)Session["nombreUsuario"];
                    int EmpresaUsuario = UsuariosFactory.EmpresaUsuario(NombreUsuario);
                    //Recogemos la fila seleccionada para editar
                    GridViewRow row = GVControles.Rows[e.RowIndex];
                    //Recogemos el DropDownList Valor de la fila seleccionada
                    DropDownList DdlValor = (DropDownList)row.FindControl("DdlValor");
                    String Valor = DdlValor.SelectedValue;
                    //Comprobamos que se han introducido datos correctos
                    //Recogemos el Id del Control Seleccionado
                    int IdControl = Int32.Parse(GVControles.Rows[row.RowIndex].Cells[1].Text);
                    e.Cancel = true;
                    GVControles.EditIndex = -1;
                    //Actualizo el control seleccionado con los valores elegidos
                    ControlesEmpresaFactory.ActualizarControlesEmpresa(EmpresaUsuario, IdControl, Valor);
                    //Comprobamos que no ha habido un cambio en el Nivel de Madurez Actual de la Empresa
                    //Recojo el valor del Nivel de Madurez Actual
                    int NivelRecienteMadurezActual = EmpresasFactory.MadurezActualEmpresa(EmpresaUsuario);
                    //Recojo los valores de los controles
                    IQueryable<ControlesEmpresa> ValoresControlesEmpresa = ControlesEmpresaFactory.RecogeControlesEmpresa(EmpresaUsuario);
                    int numTotalControles = ControlesFactory.ControlesTotales();
                    List<ControlesCheckList> ControlesChkList = new List<ControlesCheckList>(numTotalControles);
                    foreach (ControlesEmpresa ContrEmpr in ValoresControlesEmpresa)
                    {
                        ControlesCheckList nuevoContrChkList = new ControlesCheckList();
                        nuevoContrChkList.IdControl = ContrEmpr.IdControl;
                        nuevoContrChkList.IdEmpresa = ContrEmpr.IdEmpresa;
                        nuevoContrChkList.ValorControl = ContrEmpr.Valor;
                        int NivMadControl = ControlesFactory.NivelMadurezControl(nuevoContrChkList.IdControl);
                        nuevoContrChkList.NivelMadurez = NivMadControl;
                        ControlesChkList.Add(nuevoContrChkList);
                    }
                    //Calculamos el nivel de Madurez con el cambio del control editado
                    int NivelMadurezActualCalculada = EmpresasNegocio.CalcularNivelMadurezActualEmpresa(ControlesChkList, EmpresaUsuario);
                    if (NivelMadurezActualCalculada != NivelRecienteMadurezActual)
                    {
                        EmpresasFactory.InsertarNivelMadurezActual(EmpresaUsuario, NivelMadurezActualCalculada);
                        MuestraMensaje("El Control ha sido actualizado correctamente. Debido a esta modificación hubo un cambio en el nivel de madurez. El nivel es: " + NivelMadurezActualCalculada.ToString());
                    }
                    //Si no, sólo mostramos que la actualización de controles ha sido la correcta
                    else
                    {
                        MuestraMensaje("El Control ha sido actualizado correctamente.");
                    }
                }
                else
                {
                    MuestraMensaje("Elija un valor de Respuesta");
                }
                //Sea como fuere actualizamos GridView y Chart para no dejar opciones en las que se queden vacíos
                String opcion = DdlControles.SelectedValue;
                String Parametro = LblTipoActivo.Text;
                switch (opcion)
                {
                    case "RespuestasControles":
                        String ParametroSer = SerializaRespuesta(Parametro);
                        PintaChart(opcion, null);
                        LlenaGridView(opcion, ParametroSer);
                        break;
                    case "ObjetivosControl":
                        int IdDominioSelect = int.Parse(DdlDominio.SelectedValue);
                        //PintaChartDominio(IdDominioSelect);
                        LlenaGridView(opcion, Parametro);
                        break;
                    default:
                        PintaChart("RespuestasControles", null);
                        break;
                }
            }
            catch (Exception e1)
            {
                e1.ToString();
                MuestraMensaje("Error al actualizar el control");
            }
        }

        protected void GVControles_PageIndexChanging(object sender, GridViewPageEventArgs e)
        {
            try
            {
                //Recogemos la empresa asociada al usuario que inició la sesión
                String NombreUsuario = (String)Session["nombreUsuario"];
                int EmpresaUsuario = UsuariosFactory.EmpresaUsuario(NombreUsuario);
                this.GVControles.PageIndex = e.NewPageIndex;
                ModeloContainer agenteBD = new ModeloContainer();
                String opcion = DdlControles.SelectedValue;
                String Parametro = LblTipoActivo.Text;
                List<ControlEmpresaAux> ListaControles = new List<ControlEmpresaAux>();
                switch (opcion)
                {
                    case "RespuestasControles":
                        LlenaGridView(opcion, Parametro);
                        //PintaChart(opcion, null);
                        break;
                    case "ObjetivosControl":
                        int IdDominioSelect = int.Parse(DdlDominio.SelectedValue);
                        //PintaChartDominio(IdDominioSelect);
                        LlenaGridView(opcion, Parametro);
                        break;
                    default:
                        PintaChart("RespuestasControles", null);
                        break;
                }
            }
            catch (Exception e1)
            {
                e1.ToString();
                MuestraMensaje("Error al actualizar la tabla con los elementos seleccionados");
            }
        }

        protected void DdlDominio_SelectedIndexChanged(object sender, EventArgs e)
        {
            //Recogemos el nuevo Dominio seleccionado en DdlDominio
            int nuevoDominio = int.Parse(DdlDominio.SelectedValue);
            //Si cambiamos de Dominio quitamos los valores de GridView que había cargados previamente
            GVControles.DataSource = null;
            DataBind();
            UpdatePanel4.Update();
            //Actualizamos el Chart y el GridView con la opción elegida
            PintaChartDominio(nuevoDominio);
        }

        private String SerializaRespuesta(String parametro)
        {
            String RespuestaSerializ = "";
            switch (parametro)
            {
                case "PARCIALMENTE":
                    RespuestaSerializ = "PARC";
                    break;
                case "NO APLICA":
                    RespuestaSerializ = "N/A";
                    break;
                default:
                    RespuestaSerializ = parametro;
                    break;
            }
            return RespuestaSerializ;
        }
    }
}